﻿using System;
using System.Threading;
using Messages;
using Messages.Seller;
using Messages.Shop;
using Rhino.ServiceBus;
using System.Windows.Forms;
using System.Linq;

namespace Buyer
{
    class BuyerController : 
        OccasionalConsumerOf<PaymentDue>,
        OccasionalConsumerOf<ItemReady>
    {
        public Guid BuyerGuid { get; set; }
        public string Name { get; set; }
        public string Item { get; set; }
        public ItemSize Size { get; set; }

        private readonly IServiceBus _bus;
        private ManualResetEvent _wait;
        private Form1 form;

        public BuyerUserInterface BuyerUserInterface { get; set; }

        public BuyerController(IServiceBus bus, Form1 form)
        {
            BuyerUserInterface = new BuyerUserInterface();
            this.form = form;
            _bus = bus;
        }

        public void BuyItemSync()
        {
            using (_bus.AddInstanceSubscription(this))
            {
                _wait = new ManualResetEvent(false);

                var orderMessages = GetMessagesToSend(BuyerGuid, Name, Item, Size);

                _bus.Send(orderMessages);

                if (_wait.WaitOne(TimeSpan.FromSeconds(300), false) == false)
                    throw new InvalidOperationException("didn't get item in time");
            }
        }

        public void Consume(PaymentDue message)
        {
            if (BuyerUserInterface.ShouldPayForItem(Name, message.Amount, form) == false)
                return;

            _bus.Reply(new SubmitPayment
                {
                    Amount = message.Amount,
                    CorrelationId = message.ShopTransactionId
                });
        }

        public void Consume(ItemReady message)
        {
            BuyerUserInterface.ItemRush(Name, form);
            if (_wait != null)
                _wait.Set();
        }

        private static object[] GetMessagesToSend(Guid BuyerGuid, string Name, string Item, ItemSize Size)
        {
            return Enumerable.Range(0,1)
                .Select(i => new NewOrder { BuyerGuid = BuyerGuid, BuyerName = Name, ItemName = Item + " " + i, Size = Size })
                .Cast<object>()
                .ToArray();
        }
    }
}
